import 'dart:convert';
import 'dart:io';

import 'package:ac/data/ac_global_controller.dart';
import 'package:ac/data/ac_user_manager.dart';
import 'package:ac/route/ac_route_pages.dart';
import 'package:dio/dio.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
import 'package:get/get.dart' hide Response;
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';

import '../data/ac_device_tool.dart';

// 超时时间
class HttpOptions {
  //地址域名前缀
  static const String baseUrl = 'http://test-app.cosmofusionly.xyz/';
  static const String version = '1.0.0';

  //单位时间是ms
  static const int connectTimeout = 15000;
  static const int receiveTimeout = 15000;
  static const int sendTimeout = 15000;
}

class AcHttpRequest {
  // 单例模式使用Http类，
  static final AcHttpRequest _instance = AcHttpRequest._internal();

  factory AcHttpRequest() => _instance;

  static late final Dio dio;

  static get header {
    var headers = <String, dynamic>{};
    headers["Content-Type"] = "application/json";
    headers['device-id'] = AcDeviceTool().foDeviceId; // 设备id或者udid，保证当前设备唯一值。
    if (Platform.isAndroid) {
      headers['platform'] = 'Android';
      headers['model'] =
          AcDeviceTool().foAndroidDeviceInfo?.hardware ?? ''; // 设备型号
    } else if (Platform.isIOS) {
      headers["platform"] = "iOS";
      headers['model'] = AcDeviceTool().foIosDeviceInfo?.model; // 设备型号
    }
    headers['pkg'] = AcDeviceTool().packageInfo.packageName; // 包名
    headers['ver'] =
        AcDeviceTool().packageInfo.version; // 版本 例如1.0.0，读取实际配置的版本号
    headers['p_ver'] = AcDeviceTool().packageInfo.buildNumber; // build number
    headers['kst'] = '1'; // 固定传1
    headers['sys_lan'] = "en"; // 手机系统语言 如英文en
    headers['lang'] = "en"; // 手机系统语言 如英文en
    // ⚠️请注意：除登录接口和Config接口外，其余接口的Headers均需要附带token，格式为 Bearer拼接登录获取到的token
    if (AcUserManager.userInfoModel?.token != null) {
      headers['Authorization'] = 'Bearer${AcUserManager.userInfoModel?.token}';
    }
    return headers;
  }

  /// 内部构造方法
  AcHttpRequest._internal() {
    /// 初始化dio
    BaseOptions options = BaseOptions(
        connectTimeout:
            const Duration(milliseconds: HttpOptions.connectTimeout),
        receiveTimeout:
            const Duration(milliseconds: HttpOptions.receiveTimeout),
        sendTimeout: const Duration(milliseconds: HttpOptions.sendTimeout),
        baseUrl: HttpOptions.baseUrl);

    dio = Dio(options);


    /// 添加各种拦截器
    dio.interceptors.add(InterceptorsWrapper(
      onRequest: (RequestOptions options, handler) {
        if (options.uri.toString().contains('translation.googleapis.com')) {
          final cacheOptions = CacheOptions.fromExtra(options)!;
          options.extra = cacheOptions.copyWith(policy: CachePolicy.forceCache).toExtra();
          return handler.next(options);
        }

        return handler.next(options);
      },
    ));
    dio.interceptors.add(PrettyDioLogger(
        requestHeader: true,
        requestBody: true,
        responseHeader: true,
        responseBody: true));
  }

  /// 封装request方法
  Future<dynamic> request({
    required String path, //接口地址
    required HttpMethod method, //请求方式
    dynamic data, //数据
    String? newHost,
    Map<String, dynamic>? queryParameters,
    bool showLoading = true, //加载过程
    bool showErrorMessage = true, //返回数据
  }) async {
    const Map methodValues = {
      HttpMethod.get: 'get',
      HttpMethod.post: 'post',
      HttpMethod.put: 'put',
      HttpMethod.delete: 'delete',
      HttpMethod.patch: 'patch',
      HttpMethod.head: 'head'
    };

    //动态添加header头
    Options options = Options(
      method: methodValues[method],
      headers: header,
    );

    try {
      if (showLoading) {
        EasyLoading.show(
            status: 'loading...', maskType: EasyLoadingMaskType.black);
      }
      // 检查newHost是否被提供，如果是，则更新Dio的baseUrl
      if (newHost != null && newHost.isNotEmpty) {
        AcHttpRequest.dio.options.baseUrl = newHost;
      }

      Response response = await AcHttpRequest.dio.request(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
      );
      var result = response.data;
      var str = jsonEncode(result);
      switch (result) {
        case 100103:
        case 10010303:
        case 10010304:
          Get.offNamed(AcRouteNames.login);
          return null;
      }
      if (result['code'] != 0) {
        EasyLoading.showToast(result['msg']);
        return null;
      }
      return result;
    } on DioException catch (error) {
      if (showErrorMessage) {
        EasyLoading.showToast(error.message ?? "");
      }
      return null;
    } finally {
      AcHttpRequest.dio.options.baseUrl = HttpOptions.baseUrl;
      if (showLoading) {
        EasyLoading.dismiss();
      }
    }
  }
}

enum HttpMethod {
  get,
  post,
  delete,
  put,
  patch,
  head,
}
